package com.jay.media.music.core.notification

import android.app.Notification
import android.app.Notification.VISIBILITY_PUBLIC
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.media.session.PlaybackState
import android.os.Build
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.toBitmap
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.jay.media.music.core.MusicService
import com.jay.media.music.core.R


/**
 * @author xuzhou4
 * @date 2022/3/17
 */
class PlayingNotificationImpl : PlayingNotification() {

    @RequiresApi(Build.VERSION_CODES.O)
    @Synchronized
    override fun update() {
        Log.d(TAG, "update() called $mMusic")
        this.stopped = false
        Glide.with(mService)
            .load(mMusic?.albumArt ?: R.drawable.ic_music_small)
            .error(R.drawable.ic_music_small)
            .into(object : CustomTarget<Drawable>() {
                override fun onResourceReady(
                    resource: Drawable,
                    transition: Transition<in Drawable>?
                ) {
                    Log.d(
                        TAG,
                        "onResourceReady() called with: resource = $resource, transition = $transition"
                    )
                    showNotify(resource)
                }

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    Log.d(TAG, "onLoadFailed() called with: errorDrawable = $errorDrawable")
                    errorDrawable?.also { showNotify(errorDrawable) }
                }

                override fun onLoadCleared(placeholder: Drawable?) {
                    Log.d(TAG, "onLoadCleared() called with: placeholder = $placeholder")
                }
            })

    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun showNotify(resource: Drawable) {
        val smallNotification = RemoteViews(mService.packageName, R.layout.layout_notification)
        val bigNotification = RemoteViews(mService.packageName, R.layout.layout_big_notification)

        if (!TextUtils.isEmpty(mMusic?.title) || !TextUtils.isEmpty(mMusic?.artist)) {
            smallNotification.setViewVisibility(R.id.media_titles, View.VISIBLE)
            smallNotification.setTextViewText(R.id.title, mMusic?.title)
            smallNotification.setTextViewText(R.id.text, mMusic?.artist)
        } else {
            smallNotification.setViewVisibility(R.id.media_titles, View.INVISIBLE)
        }

        if (!TextUtils.isEmpty(mMusic?.title) || !TextUtils.isEmpty(mMusic?.artist)
            || !TextUtils.isEmpty(mMusic?.album)
        ) {
            bigNotification.setViewVisibility(R.id.media_titles, View.VISIBLE)
            bigNotification.setTextViewText(R.id.title, mMusic?.title)
            bigNotification.setTextViewText(R.id.text, mMusic?.artist)
            bigNotification.setTextViewText(R.id.text2, mMusic?.album)
        } else {
            bigNotification.setViewVisibility(R.id.media_titles, View.INVISIBLE)
        }

        linkButtons(smallNotification, bigNotification)

        val isPlaying =
            mState?.state == PlaybackState.STATE_PLAYING || mState?.state == PlaybackState.STATE_BUFFERING
        val icon =
            if (isPlaying) R.drawable.ic_pause_white_24dp else R.drawable.ic_play_arrow_white_24dp
        val action: Notification.Action = Notification.Action(
            icon,
            mService.getString(R.string.action_play_pause),
            retrievePlaybackAction(MusicCmdConstants.Action.PLAYORPAUSE)
        )
        val action2: Notification.Action = Notification.Action(
            R.drawable.ic_skip_prev_white_24dp,
            mService.getString(R.string.action_previous),
            retrievePlaybackAction(MusicCmdConstants.Action.REWIND)
        )

        val action3: Notification.Action = Notification.Action(
            R.drawable.ic_skip_next_white_24dp,
            mService.getString(R.string.action_next),
            retrievePlaybackAction(MusicCmdConstants.Action.NEXT)
        )

        val bitmapDrawable = resource as BitmapDrawable
        val notificationBuilder = Notification.Builder(mService, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.music)
            .setLargeIcon(bitmapDrawable.toBitmap())
            .setContentTitle(mMusic?.title)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .setPriority(Notification.PRIORITY_MAX)
            .setVisibility(VISIBILITY_PUBLIC)
            .addAction(action2)
            .addAction(action)
            .addAction(action3)
            .setCustomContentView(smallNotification)
            .setCustomBigContentView(bigNotification)
            .setOngoing(true)

        notificationBuilder.style = Notification.MediaStyle().setMediaSession(
            mService.sessionToken
        ).setShowActionsInCompactView(0, 1, 2)
        notificationBuilder.setColor(Color.WHITE)

        updateNotifyModeAndPostNotification(notificationBuilder.build())
    }

    fun linkButtons(smallNotification: RemoteViews, bigNotification: RemoteViews) {
        val componentName = ComponentName(this.mService, MusicService::class.java)
        val prevPendingIntent =
            buildPendingIntent(this.mService, MusicCmdConstants.Action.REWIND, componentName)
        smallNotification.setOnClickPendingIntent(R.id.action_prev, prevPendingIntent)
        bigNotification.setOnClickPendingIntent(R.id.action_prev, prevPendingIntent)

        val nextPendingIntent =
            buildPendingIntent(this.mService, MusicCmdConstants.Action.NEXT, componentName)
        smallNotification.setOnClickPendingIntent(R.id.action_next, nextPendingIntent)
        bigNotification.setOnClickPendingIntent(R.id.action_next, nextPendingIntent)

        val playOrPausePendingIntent =
            buildPendingIntent(this.mService, MusicCmdConstants.Action.PLAYORPAUSE, componentName)
        smallNotification.setOnClickPendingIntent(R.id.action_play_pause, playOrPausePendingIntent)
        bigNotification.setOnClickPendingIntent(R.id.action_play_pause, playOrPausePendingIntent)
    }

    private fun buildPendingIntent(
        context: Context,
        action: String,
        componentName: ComponentName
    ): PendingIntent? {
        val intent = Intent(action)
        intent.component = componentName
        return PendingIntent.getService(context, 0, intent, FLAG_IMMUTABLE)
    }

    private fun retrievePlaybackAction(str: String): PendingIntent? {
        val componentName = ComponentName(
            mService,
            MusicService::class.java
        )
        val intent = Intent(str)
        intent.component = componentName
        return PendingIntent.getService(mService, 0, intent, FLAG_IMMUTABLE)
    }
}